#ifndef IMINTERFACES_H
#define IMINTERFACES_H

#include "Core.h"
#include "imMaths.h"

#include <list>

class iComponent;
class iEntity;

extern std::list<iComponent*> g_Comps;
extern std::list<iEntity*> g_Ents;

//
// iComponent interface
class iComponent : public iMMObj {
protected:
	iEntity* m_Owner;

	Vector3 *m_Pos, *m_Scale;
	Angle *m_Angle;
	Quaternion *m_Orientation;
public:
	iComponent(void) {g_Comps.push_back(this);}
	~iComponent(void) {g_Comps.remove(this);}

	void SetOwner(iEntity *Owner) { m_Owner = Owner; }

	virtual void Update() = 0;
};

typedef MMPtr<iComponent> pComponent;


//
// Movement controller component interface
class iMovementComponent : public iComponent {
public:
	virtual void SetPos			(const Vector3 &Pos) = 0;
	virtual void SetScale		(const Vector3 &Scale) = 0;
	virtual void SetOrientation	(const Quaternion &Orientation) = 0;

	virtual Vector3		*GetPos			() = 0;
	virtual Vector3		*GetScale		() = 0;
	virtual Quaternion	*GetOrientation	() = 0;
	virtual Matrix		GetWorld		() = 0;

	virtual void Update() = 0;
};

//
// iEntity interface
class iEntity {
	std::list<pComponent> m_Components;
	iMovementComponent *m_MoveComponent;
public:
	iEntity(void) {g_Ents.push_back(this);}
	~iEntity(void) {g_Ents.remove(this);}

	void SetPos			(const Vector3 &Pos)		{ m_MoveComponent->SetPos(Pos); }
	void SetScale		(const Vector3 &Scale)		{ m_MoveComponent->SetScale(Scale); }
	void SetOrientation	(const Quaternion &Orient)	{ m_MoveComponent->SetOrientation(Orient); }

	Vector3		*GetPos()			{ return m_MoveComponent->GetPos(); }
	Vector3		*GetScale()			{ return m_MoveComponent->GetScale(); }
	Quaternion	*GetOrientation()	{ return m_MoveComponent->GetOrientation(); }

	void AddComponent			(iComponent* c)			{ m_Components.push_back(c); c->SetOwner(this); }
	void RemoveComponent		(iComponent* c)			{ m_Components.remove(c); }
	void SetMovementComponent	(iMovementComponent* c)	{ AddComponent(c); m_MoveComponent = c; }
	iMovementComponent* GetMovementComponent() { return m_MoveComponent; }
};

#endif